package com.jiangli.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.jiangli.dto.FeedbackDTO;
import com.jiangli.dto.FeedbackQureyDTO;
import com.jiangli.entity.Feedback;
import com.jiangli.mapper.FeedbackMapper;
import com.jiangli.result.PageResult;
import com.jiangli.service.FeedbackService;
import com.jiangli.utils.RedisLock;
import com.jiangli.vo.FeedbackVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.time.LocalDateTime;

@Service
@Slf4j
public class FeedbackServiceImpl implements FeedbackService {

    private static final String UNPROCESSED_KEY = "feedback:unprocessed_count";
    private static final String UNPROCESSED_LOCK_KEY = "feedback:unprocessed_count:lock";

    private final FeedbackMapper feedbackMapper;
    private final StringRedisTemplate stringRedisTemplate;
    private final RedisLock redisLock;
    public FeedbackServiceImpl(FeedbackMapper feedbackMapper,
                               StringRedisTemplate stringRedisTemplate,
                               RedisLock redisLock) {
        this.feedbackMapper = feedbackMapper;
        this.stringRedisTemplate = stringRedisTemplate;
        this.redisLock = redisLock;
    }
    @Override
    public boolean feedback(FeedbackDTO feedbackDTO) {
        // 1. 原子性递增计数器并返回新值
        Long newCount = stringRedisTemplate.opsForValue().increment(UNPROCESSED_KEY);
        if(newCount == null){
            newCount = getUnprocessedCount();
        }
        if(newCount == null){
            return false;
        }
        // 2. 首次提交时初始化计数器（避免null）
        if (newCount == 1) {
            // 从数据库同步初始值后再+1（防止冷启动时计数为0）
            Long initCount = feedbackMapper.countUnaccepted();
            newCount = stringRedisTemplate.opsForValue().increment(UNPROCESSED_KEY, initCount);
        }

        // 3. 判断是否超过阈值（递增后的值 > 阈值则回滚）
        if (newCount!=null &&newCount > 100) {
            // 超过阈值，计数器回减
            stringRedisTemplate.opsForValue().decrement(UNPROCESSED_KEY);
            return false;
        }

        // 4. 原子性保存反馈（确保计数器与数据库一致）
        try {
            Feedback feedback = new Feedback();
            BeanUtils.copyProperties(feedbackDTO, feedback);
            feedback.setCreateTime(LocalDateTime.now());
            feedback.setStatus(0);
            feedbackMapper.add(feedback);
            return true;
        } catch (Exception e) {
            // 保存失败，计数器回减
            stringRedisTemplate.opsForValue().decrement(UNPROCESSED_KEY);
            return false;
        }
    }

    @Override
    public PageResult get(FeedbackQureyDTO feedbackQureDTO) {
        PageHelper.startPage(feedbackQureDTO.getPage(),feedbackQureDTO.getPageSize());
        log.info("{}",feedbackQureDTO.getStatus());
        Page<FeedbackVO> page = feedbackMapper.get(feedbackQureDTO);
        PageResult pageResult = new PageResult();
        pageResult.setTotal(page.getTotal());
        pageResult.setRecords(page.getResult());
        return pageResult;
    }

    @Override
    public void reviseFeedback(Long feedbackId, int status) {

        feedbackMapper.revise(feedbackId,status);
        if(status == 0){
            stringRedisTemplate.opsForValue().increment(UNPROCESSED_KEY);
        }else{
            stringRedisTemplate.opsForValue().decrement(UNPROCESSED_KEY);
        }
    }

    @Override
    public void deleteFeedback(Long feedbackId) {
        feedbackMapper.delete(feedbackId);
        stringRedisTemplate.opsForValue().decrement(UNPROCESSED_KEY);
    }
    @PostConstruct
    public void initUnacceptedCount() {
        // 加锁初始化，防止与业务操作冲突
        redisLock.executeWithLock(UNPROCESSED_LOCK_KEY, ()->{
            Long count = feedbackMapper.countUnaccepted();
            stringRedisTemplate.opsForValue().set(UNPROCESSED_KEY, String.valueOf(count));
            return null;
        });
    }
    public Long getUnprocessedCount() {
        // 1. 先无锁查询Redis
        String unprocessedCount = stringRedisTemplate.opsForValue().get(UNPROCESSED_KEY);
        if (unprocessedCount != null) {
            return Long.valueOf(unprocessedCount);
        }

        // 2. Redis无值时，加锁同步数据库（双重检查）
        return redisLock.executeWithLock(UNPROCESSED_LOCK_KEY, ()->{
            String countStr = stringRedisTemplate.opsForValue().get(UNPROCESSED_KEY);
            if (countStr != null) {
                return Long.valueOf(countStr);
            }
            Long count = feedbackMapper.countUnaccepted();
            stringRedisTemplate.opsForValue().set(UNPROCESSED_KEY, String.valueOf(count));
            return count;
        });
    }
}
